package dht.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Vector;

import dht.entity.GlobalVariables;
import dht.throwable.DhtException;
import dht.tool.CommandTool;

public class FileUtils {

	public static Vector<String> getAllFiles(File dir) {
		Vector<String> fileNames = new Vector<String>();
		if (dir.exists()) {
			File files[] = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				if (files[i].isFile()) {
					fileNames.add(files[i].getName());
				} else if (files[i].isDirectory()) {
					fileNames.addAll(getAllFiles(files[i]));
				}
			}
		}
		return fileNames;
	}

	public static void deleteFile(File file) {
		if (file.exists()) {
			if (file.isFile()) {
				file.delete();
			} else if (file.isDirectory()) {
				File files[] = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					deleteFile(files[i]);
				}
			}
			file.delete();
		}
	}

	public static void deleteFileFast(String fileName) throws DhtException {
		File file = new File(fileName);
		if (file.exists()) {
			String tmpName = "/tmp/" + IdGenerator.genRandomId();
			if (file.isFile()) {
				CommandTool.runCommand("touch " + tmpName);
				CommandTool
						.runCommand("rsync --delete-before -v --progress -status "
								+ tmpName + " " + fileName);
				CommandTool.runCommand("rm " + fileName);
				CommandTool.runCommand("rm " + tmpName);
			} else if (file.isDirectory()) {
				CommandTool.runCommand("mkdir " + tmpName);
				CommandTool
						.runCommand("rsync --delete-before -v --progress -status "
								+ tmpName + "/ " + fileName);
				CommandTool.runCommand("rmdir " + fileName);
				CommandTool.runCommand("rmdir " + tmpName);
			}
		}
	}

	public static void createDir(String path) throws DhtException {
		File dir = new File(path);
		if (dir.exists()) {
			return;
		}
		if (!dir.mkdirs()) {
			throw new DhtException("directory create failed: " + path);
		}
	}

	public static byte[] readFile(String fileName) throws DhtException {
		System.out.println("read " + fileName);
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(fileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new DhtException(e.getMessage());
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[GlobalVariables.readBufferSize];
		int len;
		try {
			while ((len = fis.read(buffer)) != -1) {
				baos.write(buffer, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new DhtException(e.getMessage());
		}
		try {
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new DhtException(e.getMessage());
		}
		return baos.toByteArray();
	}

	public static void writeFile(String fileName, boolean overwrite,
			byte[] contents) throws DhtException {
		System.out
				.println("writeFile " + fileName + " overwrite: " + overwrite);
		File file = new File(fileName);
		if (file.exists() && !overwrite) {
			throw new DhtException("file already exists");
		}
		createDir(file.getParent());
		int offset = 0;
		int size = 0;
		if (contents != null) {
			size = contents.length;
		}
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(fileName);
			while (offset < size) {
				int len = Math.min(GlobalVariables.writeBufferSize, size
						- offset);
				fos.write(contents, offset, len);
				offset += len;
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new DhtException(e.getMessage());
		} catch (IOException e) {
			e.printStackTrace();
			throw new DhtException(e.getMessage());
		} finally {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
				throw new DhtException(e.getMessage());
			}
		}

	}

	public static void createFile(String fileName, byte[] contents)
			throws DhtException {
		System.out.println("createFile " + fileName);
		writeFile(fileName, false, contents);
	}

	public static void createEmptyFile(String fileName, int fileSize)
			throws DhtException {
		System.out.println("createEmptyFile " + fileName);
		File file = new File(fileName);
		createDir(file.getParent());
		try {
			if (!file.createNewFile()) {
				throw new DhtException("file create failed: " + fileName);
			}
		} catch (IOException e) {
			throw new DhtException("file create failed: " + fileName);
		}
		RandomAccessFile raf = null;
		try {
			raf = new RandomAccessFile(fileName, "rw");
			raf.setLength(fileSize);
			raf.close();
		} catch (FileNotFoundException e) {
			throw new DhtException(e.getMessage());
		} catch (IOException e) {
			throw new DhtException(e.getMessage());
		}
	}

	public static void main(String[] args) throws Exception {
		FileUtils.createEmptyFile("abc", 1024 * 1024 * 1024);
	}
}
